#ifndef CPU_INSTR_H
#define CPU_INSTR_H

#include "types.h"

/**
 * 从指定的16 位 I/O 端口读取一个8 位（字节）数据
 */
static inline uint8_t inb(uint16_t port)
{
    uint8_t rv;
    __asm__ __volatile__("inb %[p], %[v]" : [v]"=a"(rv) : [p]"d"(port));
    return rv;
}

/**
 * 向指定的16 位 I/O 端口写入一个8 位（字节）数据
 */
static inline void outb(uint16_t port, uint8_t data)
{
    __asm__ __volatile__("outb %[v], %[p]" : : [p] "d"(port), [v] "a"(data));
}

/**
 * 清除中断标志，禁止中断
 */
static inline void cli()
{
    __asm__ __volatile__("cli");
}

/**
 * 设置中断标志，允许中断
 */
static inline void sti()
{
    __asm__ __volatile__("sti");
}

/**
 * 加载全局描述符表寄存器
 * @param start GDT表起始地址
 * @param size GDT表大小
 */
static inline void lgdt(uint32_t start, uint32_t size)
{
    struct
    {
        uint16_t limit;
        uint16_t start15_0;
        uint16_t start31_16;
    } gdt;

    gdt.start31_16 = start >> 16;
    gdt.start15_0 = start & 0xFFFF;
    gdt.limit = size - 1;

    __asm__ __volatile__
    ("lgdt %[g]" 
        :
        :[g] "m"(gdt)
    );
}

/**
 * 读取CR0寄存器值
 */
static inline uint32_t read_cr0()
{
    uint32_t cr0;
    __asm__ __volatile__("mov %%cr0, %[v]" : [v] "=r"(cr0));
    return cr0;
}

/**
 * 写入CR0寄存器值
 */
static inline void write_cr0(uint32_t v)
{
    __asm__ __volatile__
    ("mov %[v], %%cr0" 
        :
        :[v] "r"(v)
    );
}

/**
 * 远跳转
 * @param selector 代码段选择子
 * @param offset 偏移地址
 */
static inline void far_jump(uint32_t selector, uint32_t offset)
{
    uint32_t addr[] = {offset, selector};
    __asm__ __volatile__("ljmpl *(%[a])" ::[a] "r"(addr));
}

/**
 * 从指定的16 位 I/O 端口读取一个16 位（字）数据
 */
static inline uint16_t inw(uint16_t port)
{
    uint16_t rv;
    // in ax, dx
    __asm__ __volatile__("in %[p], %[v]" : [v] "=a"(rv) : [p] "d"(port));
    return rv;
}

#endif  // CPU_INSTR_H